
import {
  Component,
  OnInit,
  HostBinding,
  ViewEncapsulation,
  ChangeDetectorRef,
  Input,
  ViewChild,
  forwardRef,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { reqAnimFrame } from '../shared/request-animation';

interface TimeUnitInterface {
  index: number;
  name: string;
}

@Component({
  selector: 'fui-timepicker-inner',
  templateUrl: './timepicker-inner.component.html',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TimepickerInnerComponent),
      multi: true,
    },
  ],
})
export class TimepickerInnerComponent implements OnInit, ControlValueAccessor {
  @HostBinding('class.fui-timepicker-inner') hostClass = true;

  now = new Date();
  hourList: Array<TimeUnitInterface> = [];
  minuteList: Array<TimeUnitInterface> = [];
  secondList: Array<TimeUnitInterface> = [];
  selectedHour = this.now.getHours();
  selectedMinute = this.now.getMinutes();
  selectedSecond = this.now.getSeconds();
  onChange: any = Function.prototype;
  onTouched: any = Function.prototype;

  @ViewChild('hourListInstance', { static: false }) hourListInstance;
  @ViewChild('minuteListInstance', { static: false }) minuteListInstance;
  @ViewChild('secondListInstance', { static: false }) secondListInstance;

  /** Show hour section. */
  @Input() allowHour = true;

  /** Show minute section. */
  @Input() allowMinute = true;

  /** Show second section. */
  @Input() allowSecond = true;

  valueSource: Date = null;
  set value(value: Date) {
    if (this.valueSource === value) {
      return;
    }
    this.valueSource = value;
    this.selectedHour = this.valueSource && this.valueSource.getHours();
    this.selectedMinute = this.valueSource && this.valueSource.getMinutes();
    this.selectedSecond = this.valueSource && this.valueSource.getSeconds();
  }
  get value(): Date {
    return this.valueSource || this.now;
  }

  constructor() { }

  ngOnInit() {
    this.buildTime();
  }

  scrollToSelected(instance, index, duration = 0) {
    const transIndex = index;
    const currentOption = instance.children[ 0 ].children[ transIndex ] || instance.children[ 0 ].children[ 0 ];
    this.scrollTo(instance, currentOption.offsetTop, duration);
  }

  // got from rc-timepicker
  scrollTo(element, to, duration) {
    if (duration <= 0) {
      element.scrollTop = to;
      return;
    }
    const difference = to - element.scrollTop;
    const perTick = difference / duration * 10;

    reqAnimFrame(() => {
      element.scrollTop = element.scrollTop + perTick;
      if (element.scrollTop === to) {
        return;
      }
      this.scrollTo(element, to, duration - 10);
    });
  }

  selectHour(instance, index, disabled) {
    if (disabled) {
      return;
    }
    this.scrollToSelected(instance, index, 120);
    this.selectedHour = index;
    const currentValue = new Date(this.value.getTime());
    currentValue.setHours(index);
    this.value = currentValue;
    this.onChange(this.valueSource);
    this.buildMinutes();
  }

  selectMinute(instance, index, disabled) {
    if (disabled) {
      return;
    }
    this.scrollToSelected(instance, index, 120);
    this.selectedMinute = index;
    const currentValue = new Date(this.value.getTime());
    currentValue.setMinutes(index);
    this.value = currentValue;
    this.onChange(this.valueSource);
  }

  selectSecond(instance, index, disabled) {
    if (disabled) {
      return;
    }
    this.scrollToSelected(instance, index, 120);
    this.selectedSecond = index;
    const currentValue = new Date(this.value.getTime());
    currentValue.setSeconds(index);
    this.value = currentValue;
    this.onChange(this.valueSource);
  }

  initPosition() {
    this.selectedHour = this.value.getHours();
    this.selectedMinute = this.value.getMinutes();
    if (this.hourListInstance) {
      this.scrollToSelected(this.hourListInstance.nativeElement, this.selectedHour, 0);
    }
    if (this.minuteListInstance) {
      this.scrollToSelected(this.minuteListInstance.nativeElement, this.selectedMinute, 0);
    }
    if (this.secondListInstance) {
      this.scrollToSelected(this.secondListInstance.nativeElement, this.selectedSecond, 0);
    }
  }

  buildTime() {
    this.buildHours();
    this.buildMinutes();
    this.buildSeconds();
  }

  buildHours() {
    this.hourList = [];
    for (let i = 0; i <= 23; i++) {
      this.hourList.push({
        name: i.toString().length === 1 ? ('0' + i) : ('' + i),
        index: i,
      });
    }
  }

  buildMinutes() {
    this.minuteList = [];
    for (let i = 0; i <= 59; i++) {
      this.minuteList.push({
        name: i.toString().length === 1 ? ('0' + i) : ('' + i),
        index: i,
      });
    }
  }

  buildSeconds() {
    this.secondList = [];
    for (let i = 0; i <= 59; i++) {
      this.secondList.push({
        name: i.toString().length === 1 ? ('0' + i) : ('' + i),
        index: i,
      });
    }
  }

  writeValue(value: any): void {
    this.value = value;
    this.onChange(this.valueSource);
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
}
